
# 2.1.2 入门 ------------------------------------

# 导入 torch
import torch

# 不要写 x = torch.range(1,19,2) 已弃用
x = torch.arange(1,19,2)

print(x)
# 输出：tensor([ 1,  3,  5,  7,  9, 11, 13, 15, 17])

# shape属性来访问张量（沿每个轴的长度）的形状
print(x.shape)
# 输出：torch.Size([9])

# 张量中元素的总数
print(x.numel())
# 输出：9

# 改变一个张量的形状而不改变元素数量和元素值
# X = x.reshape(3, 4)
# print(X)

# 在知道宽度后，高度会被自动计算得出，可用 -1 来调用此自动计算出维度的功能
X = x.reshape(3, -1)
print(X)
# 输出：tensor([[ 1,  3,  5],
#         [ 7,  9, 11],
#         [13, 15, 17]])

#全 0 矩阵
y = torch.zeros((2 , 3 , 4))
print(y)

# 全 1 矩阵
y = torch.ones(2 , 3 , 4)
print(y)
# 输出：tensor([[[1., 1., 1., 1.],
#          [1., 1., 1., 1.],
#          [1., 1., 1., 1.]],
#
#         [[1., 1., 1., 1.],
#          [1., 1., 1., 1.],
#          [1., 1., 1., 1.]]])

# 随机初始化
# 每个元素都从均值为0、标准差为1的标准高斯分布（正态分布）中随机采样
y = torch.randn(3,4)
print(y)
# 输出：tensor([[-1.5440, -0.2916,  0.0764, -0.6154],
#         [ 0.3609, -0.4223, -1.8908,  1.0304],
#         [-0.9894, -0.8672,  1.0083,  0.7612]])

#
y = torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
print(y)
# 输出：tensor([[2, 1, 4, 3],
#         [1, 2, 3, 4],
#         [4, 3, 2, 1]])



# 2.1.2 运算符 ------------------------------------
# 元素个数要一致
x = torch.tensor([1,2,3,4])
y = torch.tensor([5,6,7,8])
print(x-y)
print(x**y)
# 输出：tensor([-4, -4, -4, -4])
# tensor([    1,    64,  2187, 65536])

# 张量连结
x = torch.arange(12,dtype=torch.float).reshape(3,4)
y = torch.tensor([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
X = torch.cat((x,y),dim=0)  # 行
Y = torch.cat((x,y),dim=1)  # 列
print(X)
print(Y)
# 输出：tensor([[ 0.,  1.,  2.,  3.],
#         [ 4.,  5.,  6.,  7.],
#         [ 8.,  9., 10., 11.],
#         [ 1.,  2.,  3.,  4.],
#         [ 5.,  6.,  7.,  8.],
#         [ 9., 10., 11., 12.]])
# tensor([[ 0.,  1.,  2.,  3.,  1.,  2.,  3.,  4.],
#         [ 4.,  5.,  6.,  7.,  5.,  6.,  7.,  8.],
#         [ 8.,  9., 10., 11.,  9., 10., 11., 12.]])

# 要求形状一致
# print(X == Y)

print(X.sum())
# 输出：tensor(144.)    有小数点
print(y.sum())
# 输出：tensor(78)     无小数点



# 2.1.3 广播机制------------------------------------

# 矩阵a将复制列， 矩阵b将复制行 自动进行
a = torch.arange(3).reshape((3,1))  # 再多一个括号视为元组，更规范
b = torch.arange(2).reshape(1,2)
print(a+b)



# 2.1.4 索引和切片------------------------------------

a = torch.arange(12)
print(a)
# 取最后一个元素
print(a[-1])
# 左闭右开
print(a[1:3])
# 写入矩阵
b = a.reshape(3,4)
# 第一维上 第一行+第二行设为 12，：为所有元素
b[0:2,:] = 12
print(b)
# 输出：
# tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])
# tensor(11)
# tensor([1, 2])



# 2.1.5 节省内存------------------------------------
a = torch.arange(12).reshape(3,4)
b = torch.arange(12).reshape(3,4)
# 形状与 a 相同的全 0 矩阵
c = torch.zeros_like(a)
print('1-id(c):', id(c))
# 原地操作
c[:] = a + b
print('2-id(c):', id(c))
c = a + b
print('3-id(c):', id(c))
#1-id(c): 1724029218848
# 2-id(c): 1724029218848
# 3-id(c): 1722775588208



# 2.1.6 转换为其他Python对象------------------------------------
# numpy tensor 互转
a = torch.arange(12).reshape(3,4)
A = a.numpy()
B = torch.tensor(A)
print(type(A))
print(type(B))
# 输出：
# <class 'numpy.ndarray'>
# <class 'torch.Tensor'>

# 张量转换为Python标量
# 只有当张量 a 包含恰好一个元素时，这个操作才能成功
a = torch.tensor([3])
print(a.item())
# 将张量内的数据值提取出来，作为一个 Python float 变量返回
b = float(a)
print(b)
b = int(a)
print(b)
# 输出：3
# 3.0
# 3